home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Internet Info 1994 March
/
Internet Info CD-ROM (Walnut Creek) (March 1994).iso
/
networking
/
cisco
/
tuecho.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-08-07
|
10KB
|
352 lines
/*
* Send / receive TCP or UDP echos in any of a number of bizzare ways.
*
* Joel P. Bion, March 1990
* Copyright (c) 1990 cisco Systems. All rights reserved.
*
* This "tuecho" program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* Prompts as:
* Host: -- host to send echos to -- can be name or a.b.c.d --
* Enter protocol (0 = UDP, 1 = TCP) [0]: -- UDP or TCP
* Size of data portion (bytes) [100]: -- bytes in data, excluding headers --
* Number of bursts [5]: -- number of bursts of packets to send --
* Packets per burst [1]: -- packets per burst, all sent AT ONCE --
* Timeout (seconds) [2]: -- how long to wait for data
* Pause interval (seconds) [0]: -- Pause interval between bursts of frames
* Type of pattern (specify = 0, increment = 1) [1]:
* -- if 0 specified, allow you to specify a 16bit pattern as four
* -- hex digits (see below). If 1, will create a "incrementing",
* -- cycling pattern from 0x0000 -> 0xffff ->.
* Enter pattern (hex value) [abcd]: -- if "0" specified above
*/
#include <signal.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <arpa/inet.h>
extern void printf(), fflush(), exit(), bzero(), perror(), strcpy(),
setbuf(), sscanf(), bcopy(), close(), fprintf();
extern int write(), read(), select(), atoi(), socket(), connect();
/* Maximum packet size (integer) */
#define MAXBUF (2000)
#define MAXBYTES (MAXBUF * 4)
/* Special patterns... */
#define SPECIAL_NONE (0)
#define SPECIAL_COUNTER (SPECIAL_NONE + 1)
#define SPECIAL_MAX (SPECIAL_COUNTER)
/* Protocols */
#define PROTO_UDP (0)
#define PROTO_TCP (PROTO_UDP + 1)
#define PROTO_MAX (PROTO_TCP)
/* Global, because interrupt routine references them */
int
lost, /* Packets whose echos are not received */
good, /* We received a good reply */
corrupted, /* We received a bad reply */
sentout, /* How many we sent out */
outc; /* How many chars out */
/* Guarantee CRs at random times */
void cprint(c)
char c;
{
printf("%c", c);
if (++outc == 70) {
printf("\n");
outc = 0;
}
fflush(stdout);
}
void cprintcr()
{
if (outc != 0)
printf("\n");
}
unsigned getint(prompt, defa, fc)
char *prompt;
unsigned defa;
char fc;
{
char s[1000];
unsigned u;
if (fc == 'x')
printf("%s [%x]: ", prompt, defa);
else
printf("%s [%d]: ", prompt, defa);
fgets(s, 999, stdin);
if ((s[0] == '\0') || (s[0] == '\n'))
return(defa);
else {
if (fc == 'x')
sscanf(s,"%x", &u);
else
sscanf(s,"%d", &u);
return(u);
}
}
void outhere()
{
cprintcr();
printf("\nAt end, sent out = %d, good = %d, lost = %d, corrupted = %d.\n",
sentout, good, lost, corrupted);
}
void outhere_exit()
{
outhere();
exit(0);
}
void usage_exit()
{
printf("usage: tuecho\n");
printf(" with no parameters will prompt you for information, or another form:\n");
printf("\n tuecho host proto size nbursts ppburst timeout pauseint ptype\n");
printf(" [pattern] (on same command line as above)\n");
printf("\n");
printf(" Where:\n");
printf(" host: host to receive your echos. (can be name or a.b.c.d form)\n");
printf(" proto: 0 for UDP, 1 for TCP\n");
printf(" size: size of echo packet, excluding headers\n");
printf(" nbursts: total number of \"bursts\" of echo packets to send\n");
printf(" ppburst: how many echo packets should be in each burst\n");
printf(" timeout: how many seconds to wait for the reply (allow more time for bursts)\n");
printf(" pauseint: Pause interval, in seconds, between bursts\n");
printf(" ptype: 0 to allow you to specify a hex pattern as the final \"pattern\" parameter\n");
printf(" 1 for \"increasing cyclic\" 16-bit pattern going from 0x0000 to 0xffff\n");
printf(" and back again, until each echo packet is filled\n");
printf(" pattern: four character hex pattern (no leading 0x), if ptype = 1, to insert repeatedly\n");
printf(" in the echo packets\n");
exit(0);
}
void sendrecvechos(sock, ptype, pattern, bufsize, bursts, burstsize, timeout,
pause_int)
int sock; /* Socket to send / receive from */
int ptype; /* Pattern type (normal, or a special) */
int pattern; /* Pattern (if normal) */
int bufsize; /* Buffer size to send */
int bursts; /* Number of bursts */
int burstsize; /* Size of bursts */
struct timeval timeout; /* Timeout */
int pause_int; /* Pause interval */
{
int i, j, k, ok, readin;
int nb;
unsigned int bufo[MAXBUF]; /* Packet to send out */
unsigned int bufi[MAXBUF]; /* Packet to accept */
fd_set readmask; /* For "select" call */
/* Set up select mask */
FD_ZERO(&readmask);
FD_SET(sock, &readmask);
/* Set up the pattern. Check for specials... */
switch (ptype) {
case SPECIAL_COUNTER:
for (i = 0; i < (bufsize / 4); i++)
bufo[i] = i;
break;
case SPECIAL_NONE:
default:
for (i = 0; i < (bufsize / 4); i++)
bufo[i] = pattern;
break;
}
for (i = 0; (i < bursts); i++) {
if (pause_int)
sleep(pause_int);
if (ptype == SPECIAL_COUNTER)
bufo[0] = i;
for (j = 0; j < burstsize; j++) {
if (write(sock, (char *) bufo, bufsize) < 0) {
perror("writing on datagram socket.");
outhere();
exit(1);
}
sentout++;
}
for (j = 0; j < burstsize; j++) {
nb = select(FD_SETSIZE, &readmask, (fd_set *) 0,
(fd_set *) 0, &timeout);
if (nb <= 0) {
lost++;
cprint('.');
FD_SET(sock, &readmask);
continue;
}
if (FD_ISSET(sock, &readmask)) {
bzero((char *) bufi, bufsize);
if ((readin = read(sock, (char *) bufi, bufsize)) < 0) {
perror("Reading on datagram socket.");
outhere();
exit(1);
} else {
ok = 1;
for (k = 0; ((k < (bufsize / 4)) && (ok)); k++)
ok = (bufo[k] == bufi[k]);
if (!(ok)) {
corrupted++;
cprint('*');
continue;
} else {
good++;
cprint('!');
continue;
}
}
}
}
}
outhere();
}
void printinfo(ptype, pattern, bufsize, bursts, burstsize, timeout, server,
proto, pause_int)
int ptype; /* Pattern type (normal, or a special) */
int pattern; /* Pattern (if normal) */
int bufsize; /* Buffer size to send */
int bursts; /* Number of bursts */
int burstsize; /* Size of bursts */
struct timeval timeout; /* Timeout */
struct sockaddr_in server; /* Remote server IP address */
int proto; /* Protocol */
int pause_int;
{
printf("\nSending %d bursts of %d %s packets, data portions being %d bytes,\n",
bursts, burstsize, ((proto == PROTO_TCP) ? ("TCP") : ("UDP")),
bufsize);
printf("with a timeout of %d seconds,\nthe pattern being ",
timeout.tv_sec);
switch (ptype) {
case SPECIAL_COUNTER:
printf("an incrementing value in the packet");
break;
case SPECIAL_NONE:
default:
printf("0x%x in each four bytes", pattern);
break;
}
printf("\n");
printf("Pause interval: %d seconds\n", pause_int);
printf("Sending to IP address %u.%u.%u.%u...\n",
(unsigned) server.sin_addr.S_un.S_un_b.s_b1,
(unsigned) server.sin_addr.S_un.S_un_b.s_b2,
(unsigned)server.sin_addr.S_un.S_un_b.s_b3,
(unsigned) server.sin_addr.S_un.S_un_b.s_b4);
}
void askinfo(argc, argv, hostname, proto,
bufsize, bursts, burstsize, timeout, ptype, pattern, pause_int)
int argc;
char **argv, *hostname;
int *proto, *bufsize, *bursts, *burstsize;
struct timeval *timeout;
int *ptype;
unsigned *pattern;
int *pause_int;
{
if ((argc > 9) || ((argc == 2) && (argv[1][0] == '-') &&
(argv[1][1] == 'h')))
usage_exit();
if (argc > 1)
strcpy(hostname, argv[1]);
else {
printf("Host: ");
gets(hostname);
}
*proto = ((argc > 2) ? (atoi(argv[2])) :
(int) getint("Enter protocol (0 = UDP, 1 = TCP)", 0, 'd'));
*bufsize = ((argc > 3) ? (atoi(argv[3])) :
(int) getint("Size of data portion (bytes)", 100, 'd'));
*bursts = ((argc > 4) ? (atoi(argv[4])) :
(int) getint("Number of bursts", 5, 'd'));
*burstsize = ((argc > 5) ? (atoi(argv[5])) :
(int) getint("Packets per burst", 1, 'd'));
timeout->tv_sec = ((argc > 6) ? (atoi(argv[6])) :
(int) getint("Timeout (seconds)", 2, 'd'));
*pause_int = ((argc > 7) ? (atoi(argv[7])) :
(int) getint("Enter pause interval", 0, 'd'));
*ptype = ((argc > 8) ? (atoi(argv[8])) :
(int) getint("Type of pattern (specify = 0, increment = 1)",
1, 'd'));
if (*ptype == SPECIAL_NONE)
if (argc > 9)
sscanf(argv[9], "%x", pattern);
else
*pattern = getint("Enter pattern (hex value)", 0xabcd, 'x');
}
void init()
{
setbuf(stdout, NULL);
good = sentout = corrupted = lost = outc = 0;
}
void main(argc, argv)
int argc;
char **argv;
{
char hostname[1000];
int bufsize, bursts, proto, ptype, burstsize, sock;
struct hostent *hp, *gethostbyname();
struct in_addr ip;
struct sockaddr_in server;
struct timeval timeout;
unsigned int pattern, pause_int;
askinfo(argc, argv, hostname, &proto, &bufsize, &bursts, &burstsize,
&timeout, &ptype, &pattern, &pause_int);
signal(SIGINT, outhere_exit);
ip.s_addr = inet_addr(hostname);
if (ip.s_addr == -1) {
hp = gethostbyname(hostname);
if (hp == NULL) {
fprintf(stderr, "%s: %s: unknown host\n", argv[0],
argv[1]);
exit(1);
}
bcopy(hp->h_addr, &server.sin_addr, hp->h_length);
} else
bcopy(&ip, &server.sin_addr, sizeof(ip));
printinfo(ptype, pattern, bufsize, bursts, burstsize, timeout, server,
proto, pause_int);
sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock < 0) {
perror("Opening stream socket.");
exit(1);
}
server.sin_family = AF_INET;
server.sin_port = htons(((struct servent *)
getservbyname("echo",((proto == PROTO_UDP) ?
("udp") : ("tcp")
)))->s_port);
if (connect(sock, &server, sizeof(server)) < 0) {
perror("connecting stream socket");
exit(1);
}
sendrecvechos(sock, ptype, pattern, bufsize, bursts, burstsize, timeout,
pause_int);
close(sock);
exit(0);
}